#include "gd32w51x.h"
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "DevicesFlash.h"


int8_t cFlashWriteDatas(uint32_t uiAddress, void *pvBuff, int32_t iLength)
{
    uint32_t *puiDataAddress = (uint32_t *)pvBuff;
    int8_t cError = 0, cCnt = 0;

    if((iLength < 0) || ((uiAddress + iLength) > FLASH_USER_MAX_ADDR))
    {
        printf("cFlashWriteDatas uiAddress: %08X iLength: %d >= FLASH_USER_MAX_ADDR.\r\n", uiAddress, iLength);
        return 1;
    }

    /* unlock the flash program/erase controller */
    fmc_unlock();

    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_OBERR);

    /* 每次写入4字节 */
    while(iLength > 0)
    {
        /* erase the flash pages */
        if((uiAddress % FLASH_PAGE_SIZE) == 0)
        {
            cCnt = 8;
            while((fmc_page_erase(uiAddress) != FMC_READY) && (--cCnt));

            fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_OBERR);

            if(cCnt == 0)
            {
                printf("cFlashWriteDatas fmc_page_erase addr: 0x%08X error.\r\n", (unsigned int)uiAddress);
                cError |= 2;
                break;
            }
        }

        /* program flash */
        if((*(uint32_t *)uiAddress != *puiDataAddress) && (fmc_word_program(uiAddress, *puiDataAddress) != FMC_READY))
        {
            printf("cFlashWriteDatas fmc_word_program addr: 0x%08X error!\r\n", (unsigned int)uiAddress);
            cError |= 4;
            break;
        }

        fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_OBERR);

        ++puiDataAddress;
        uiAddress += 4;
        iLength -= 4;
    }

    /* lock the main FMC after the program operation */
    fmc_lock();

    return cError;
}

int8_t cFlashReadDatas(uint32_t uiAddress, void *pvBuff, int32_t iLength)
{
    if((iLength < 0) || ((uiAddress + iLength) > FLASH_USER_MAX_ADDR))
    {
        printf("cFlashReadDatas uiAddress: 0x%08X iLength: %d > FLASH_USER_MAX_ADDR.\r\n", uiAddress, iLength);
        return 1;
    }

    while(icache_flag_get(ICACHE_BUSY_FLAG) != RESET);
    /* enable icache */
    icache_disable();

    /* Read Flash */
    memcpy(pvBuff, (uint8_t*)uiAddress, iLength);

    /* enable icache */
    icache_enable();
    while((ICACHE_CTL & ICACHE_CTL_EN) == RESET);

    return 0;
}
